package com.eunion.web.admin.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.eunion.core.LogUtil;
import com.eunion.core.PageData;
import com.eunion.core.common.DeleteVo;
import com.eunion.core.common.JsonVo;
import com.eunion.core.common.ZtreeStringVo;
import com.eunion.core.exception.ValidateException;
import com.eunion.web.admin.bo.AdminRoleAuthBo;
import com.eunion.web.admin.entity.AdminRole;
import com.eunion.web.admin.service.AdminAuthService;
import com.eunion.web.admin.service.AdminRoleService;
import com.eunion.web.common.base.BaseService;
import com.eunion.web.common.base.BaseTableCommonController;
import com.eunion.web.common.vo.Web;
import com.eunion.common.util.CommUtils;
import com.eunion.common.util.RegUtils;

/**
 * 角色.
 *
 * @since 2016年12月20日
 */
@Controller
@RequestMapping(value = "/admin/adminrole")
public class AdminRoleController extends BaseTableCommonController<AdminRole, String> {
    
    // @RequiresPermissions("admin:role:main")
    @Override
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
    public String main(PageData<AdminRole> pages, Model model) {
//        List<AdminAuth> jdbcTemplateTest =  adminAuthService.getAllAdminAuth();
//        List<Object[]> a = adminRoleService.groupBySql();
//        List<Object[]> b = adminRoleService.groupByHql();
//        List<Object[]> c =  adminRoleService.groupBySpecification();
        
        setModuleQuery(model);
        model.addAttribute("pages", pages);
        return getUrlBase();
    }
    
    /**
     * Post 保存对象.
     */
    @PreAuthorize("hasAuthority('admin:role:add')")
    // @RequiresPermissions("admin:role:add")
    @RequestMapping(value = Web.URL_SEP_SAVE, method = {RequestMethod.POST})
    public String save(@Valid AdminRole obj, BindingResult result, Model model) {
        try {
            checkBindResult(result);// 检查bindingresult中是否有异常.
            if (StringUtils.isNotEmpty(obj.getRoleCode()) && !RegUtils.checkCharactersORNumbers(obj.getRoleCode(), 2, 20)) {
                throw new ValidateException("请输入合法的角色代码");
            }
            if (StringUtils.isNotEmpty(obj.getRoleName()) && !RegUtils.checkCharacterORChineseORNumerals(obj.getRoleName(), 2, 20)) {
                throw new ValidateException("请输入合法的角色名字");
            }
            List<AdminRole> objDb = adminRoleService.findByRoleCodeOrRoleName(obj.getRoleCode(), obj.getRoleName());
            if (objDb != null && objDb.size() > 0) {
                setModuleAdd(model);
                model.addAttribute(Web.OBJ, obj);
                setModuleStatusError(model, "角色代码或名字已存在!");
                return getUrlBase().concat("-add");
            }
            obj.setCreatedTime(CommUtils.getDayTimestamp());
            obj.setCreatedBy(getSessionUserName());
            setModuleStatusOK(model);
            getBaseService().save(obj);
            // model.addAttribute(Web.OBJ, new AdminRole());
            setModuleStatusOK(model, "新增成功");
        } catch (ValidateException ve) {
            model.addAttribute(Web.OBJ, obj);
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            model.addAttribute(Web.OBJ, obj);
            LogUtil.get(this.getClass()).error("save obj error : {}", e);
            setModuleStatusError(model, "新增失败");
        }
        setModuleAdd(model);
        return getUrlBase().concat("-add");
    }
    
    /**
     * Post 更新对象.
     */
    @PreAuthorize("hasAuthority('admin:role:edit')")
    @RequestMapping(value = Web.URL_SEP_UPDATE, method = {RequestMethod.POST})
    public String update(@Valid AdminRole obj, BindingResult result, Model model) {
        try {
            setModuleEdit(model);
            model.addAttribute(Web.OBJ, obj);
            checkBindResult(result);// 检查bindingresult中是否有异常.
            if (StringUtils.isNotEmpty(obj.getRoleCode()) && !RegUtils.checkCharactersORNumbers(obj.getRoleCode(), 2, 20)) {
                throw new ValidateException("请输入合法的角色代码");
            }
            if (StringUtils.isNotEmpty(obj.getRoleName()) && !RegUtils.checkCharacterORChineseORNumerals(obj.getRoleName(), 2, 20)) {
                throw new ValidateException("请输入合法的角色名字");
            }
            AdminRole objDb = adminRoleService.findOne(obj.getRoleCode());
            if (objDb == null) {
                setModuleAdd(model);
                setModuleStatusError(model, "角色不存在!");
                return getUrlBase().concat("-edit");
            }
            objDb.setUpdatedTime(CommUtils.getDayTimestamp());
            obj.setUpdatedBy(getSessionUserName());
            // 检查名字是否为唯一
            if (!objDb.getRoleName().equals(obj.getRoleName())) {
                List<AdminRole> objCheckList = adminRoleService.findByRoleCodeOrRoleName(obj.getRoleCode(), obj.getRoleName());
                if (objCheckList != null && objCheckList.size() > 1) {
                    setModuleAdd(model);
                    setModuleStatusError(model, "角色名字已存在!");
                    return getUrlBase().concat("-edit");
                }
            }
            objDb.setRoleName(obj.getRoleName());
            objDb.setStatus(obj.getStatus());
            setModuleStatusOK(model);
            getBaseService().save(objDb);
            setModuleStatusOK(model, "更新成功");
        } catch (ValidateException ve) {
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("update obj error : {}", e);
            setModuleStatusError(model, "更新失败");
        }
        model.addAttribute(Web.OBJ, obj);
        return getUrlBase().concat("-edit");
    }
    
    /**
     * 跳转到更新页面.
     *
     * @param id    待更新的对象ID
     * @param model a holder for model attributes 数据
     * @return 更新页面
     */
    @PreAuthorize("hasAuthority('admin:role:auth')")
    @RequestMapping(value = "auth/{id}", method = RequestMethod.GET)
    public String auth(@PathVariable String id, Model model) {
        setModuleEdit(model);
        AdminRole objDb = getBaseService().findOne(id);
        model.addAttribute(Web.OBJ, objDb);
        setRoleAuthInfo(id, model);
        return getUrlBase().concat("-auth");
    }
    
    private void setRoleAuthInfo(String id, Model model) {
        // 查询角色下的权限列表
        List<String> hasAuths = adminRoleService.fingAllAuthsByRole(id);
        List<ZtreeStringVo> allAuths = adminAuthService.findAllAuthsForZtree();
        if (allAuths == null) {
            allAuths = new ArrayList<ZtreeStringVo>();
        }
        if (hasAuths != null && hasAuths.size() > 0) {
            for (ZtreeStringVo zv : allAuths) {
                if (hasAuths.contains(zv.getId())) {
                    zv.setChecked(true);// 已经选择上的设置为已选择
                }
            }
        }
        String jsonAuth = JSON.toJSONString(allAuths);
        model.addAttribute("allAuthJson", jsonAuth);
        LogUtil.get(this.getClass()).debug("jsonAuth is : {}", jsonAuth);
    }
    
    /**
     * Post 更新对象.
     */
    @PreAuthorize("hasAuthority('admin:role:auth')")
    @RequestMapping(value = "auth")
    public String auth(@Valid AdminRoleAuthBo obj, BindingResult result, Model model) {
        try {
            setModuleEdit(model);
            model.addAttribute(Web.OBJ, obj);
            checkBindResult(result);// 检查bindingresult中是否有异常.
            AdminRole objDb = adminRoleService.findOne(obj.getRoleCode());
            if (objDb == null) {
                setModuleAdd(model);
                setModuleStatusError(model, "授权失败，角色不存在!");
                return getUrlBase().concat("-auth");
            }
            String[] authCodes = obj.getAuthCodes().split(",");// 所有的权限列表
            adminRoleService.removeRoleAuths(obj.getRoleCode(), authCodes);
            setModuleStatusOK(model, "授权成功");
        } catch (ValidateException ve) {
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("update obj error : {}", e);
            setModuleStatusError(model, "授权失败");
        } finally {
            if (null != obj && StringUtils.isNotBlank(obj.getRoleCode())) {
                setRoleAuthInfo(obj.getRoleCode(), model);
            }
        }
        return getUrlBase().concat("-auth");
    }
    
    /**
     * 根据传入的数据ids,来删除对象. headers = {"Accept=application/json","Content-type=application/json" } , produces = "application/json"
     */
    @PreAuthorize("hasAuthority('admin:role:remove')")
    @RequestMapping(value = Web.URL_SEP_REMOVE, method = RequestMethod.POST)
    @ResponseBody
    @Override
    public JsonVo remove(@RequestBody DeleteVo<String> dvo) {
        try {
            if (dvo != null && dvo.getIds() != null && dvo.getIds().size() > 0) {
                // 检查有无被其他角色引用,添加索引后，默认是删除不掉的，可以先这样用者，后面改为批量删除处理
                // 2016-01-10 这里肯定要修改为批删除的，而且要重写Responsitory里的内容？
                List<AdminRole> tts = getBaseService().findAll(dvo.getIds());
                if (tts != null && !tts.isEmpty()) {
                    getBaseService().delete(tts);
                }
                return new JsonVo(true);
                
            }
            return new JsonVo(true);
        } catch (Exception e) {
            if (e instanceof DataIntegrityViolationException) {
                LogUtil.get(this.getClass()).error("删除失败，请检查是否有用户已分配过该权限", e);
                return new JsonVo(false, "删除失败，请检查是否有用户已分配过该权限。");
            }
            LogUtil.get(this.getClass()).error("remove erro ", e);
            return new JsonVo(false, "删除出现异常");
        }
    }
    
    @Override
    protected BaseService<AdminRole, String> getBaseService() {
        return adminRoleService;
    }
    
    @Override
    protected String getUrlBase() {
        return "admin/authority/role";
    }
    
    @Resource
    private AdminRoleService adminRoleService;
    
    @Resource
    private AdminAuthService adminAuthService;
    
}
